#include "ParserConsultas.h"
#include "Util.h"
using std::ifstream;

ParserConsultas::ParserConsultas(const char* archivoConsulta):archivoConsultas(archivoConsulta) {
	estado = true;
	error = "";
}

// hay q optimizarlo!!!!!!!!!!!!!!
void ParserConsultas::iniciarParseo() {
	ifstream file;
		std::string linea;
		std::string id;
		std::string codigo;
		std::string tablaActual;
		bool bconsulta = false;
		bool bfiltro = false;
		bool binput = false;
		bool bresultado = false;
		bool bgrafico = false;
		unsigned int consultasDeUnaTabla = 0;
		unsigned int numeroTab = 0;

		file.open(archivoConsultas.c_str(), ifstream::in);

		if(file.is_open()) {
			while(!file.eof()) {
				getline(file,linea);
				//if(linea[0] == Util::TABLACHAR)
					//id = getPrimerToken(linea);

				if(getPrimerToken(linea).compare(Util::TABLA) == 0) {
				//if(linea.find_first_of(Util::TABLA, 0) != std::string::npos) {
			//		std::cout<<"encontro: "<<linea<<std::endl;
					numeroTab++;
					tablaActual = Util::intToString(numeroTab);
					tablaActual.append(1, Util::SEPARADORFILECONSULTA);
					tablaActual.append(getSegundoToken(linea));

					datosDeTablas.push_back(tablaActual);
					//id = "";
					continue;
				}
				if(linea.compare(Util::FINTABLA) == 0) {
					cantConsultasPorTabla[tablaActual] = consultasDeUnaTabla;
					consultasDeUnaTabla = 0;
					continue;
				}
				if(linea.compare(Util::CONSULTA) == 0) {
					consultasDeUnaTabla++;
					continue;
				}
				if(linea.compare(Util::FINCONSULTA) == 0) {
					bgrafico = bconsulta = binput = bresultado = bfiltro = false;
					continue;
				}
				if(linea.compare(Util::FILTROS) == 0) {
					bconsulta = binput = bresultado = bgrafico = false;
					bfiltro = true;
					continue;
				}
				if(linea.compare(Util::INPUTS) == 0)  {
					bconsulta = bfiltro = bresultado = bgrafico = false;
					binput = true;
					continue;
				}
				if(linea.compare(Util::GRAFICO) == 0) {
					bconsulta = bfiltro = binput = bresultado = false;
					bgrafico = true;
					continue;
				}
				/**/
				if(bfiltro) {
					codigo = tablaActual;
					codigo.append(Util::intToString(consultasDeUnaTabla));
					mapFiltros[codigo].push_back(linea.substr(2));
					continue;
				}
				if(binput) {
					codigo = tablaActual;
					codigo.append(Util::intToString(consultasDeUnaTabla));

					id = getPrimerToken(linea);

					if(id[0] == Util::DIMENSION)
						mapInputsDimensiones[codigo].push_back(linea.substr(2));

					else
						mapInputsHechos[codigo].push_back(linea.substr(2));

					continue;
				}
				if(bgrafico) {
					codigo = tablaActual;
					codigo.append(Util::intToString(consultasDeUnaTabla));
					mapGraficos[codigo] = linea;
				}
			}
			file.close();
		}
		else {
			error = "Error al abrir el archivo de consultas";
			estado = false;
		}
}

//$ Vendedor|Sucursal|Fecha|Marca|Producto|Precio|Precio Total
std::vector<std::string> ParserConsultas::getColumnasGrafico(const std::string &linea) {
	std::vector<std::string> columnas;
	size_t pos1 = 1, pos2;

	while((pos2 = linea.find_first_of(Util::PIPE, pos1 + 1)) != std::string::npos) {
		columnas.push_back(linea.substr(pos1 + 1, pos2 - pos1 -1));
		pos1 = pos2;
	}
	columnas.push_back(linea.substr(pos1 + 1));
	return columnas;
}

std::string ParserConsultas::getDato(std::string valor, unsigned int numero) {
	valor.append(Util::intToString(numero));
	return valor;
}
std::vector<std::string>& ParserConsultas::getFiltros(std::string &datosDeTabla, unsigned int consulta) {
	return mapFiltros[getDato(datosDeTabla, consulta)];
}

std::vector<std::string>& ParserConsultas::getInputsHechos(std::string &datosDeTabla, unsigned int consulta) {
	return mapInputsHechos[getDato(datosDeTabla, consulta)];
}

std::vector<std::string>& ParserConsultas::getInputsDimensiones(std::string &datosDeTabla, unsigned int consulta) {
	return mapInputsDimensiones[getDato(datosDeTabla, consulta)];
}

std::string ParserConsultas::getGrafico(std::string &datosDeTabla, unsigned int consulta) {
	return mapGraficos[getDato(datosDeTabla, consulta)];
}

unsigned int ParserConsultas::getCantidadconsultasDeTabla(std::string & tabla) {
	return cantConsultasPorTabla[tabla];
}

std::vector<std::string>& ParserConsultas::getDatosDeTablas() {
	return datosDeTablas;
}
// debe ser seguro!!
std::string ParserConsultas::getPrimerToken(std::string &linea) {
	size_t pos = linea.find_first_of(Util::SEPARADORFILECONSULTA, 0);

	if(pos != string::npos)
		return linea.substr(0, pos);
	return linea;
}

std::string ParserConsultas::getSegundoToken(std::string &linea) {
	size_t pos = linea.find_first_of(Util::SEPARADORFILECONSULTA, 0);
	return linea.substr(pos + 1);
}

bool ParserConsultas::getEstado() {
	return estado;
}
/*
std::vector<std::string>& ParserConsultas::getVector()   {
	return nombresTablas;
}
*/
std::string ParserConsultas::getError() {
	return error;
}
bool ParserConsultas::hayFiltro(std::string &datosDeTabla, unsigned int consulta) {
	std::string buscado = getDato(datosDeTabla, consulta);

	std::map<std::string, std::vector<std::string> >::iterator it = mapFiltros.begin();
	for(; it != mapFiltros.end(); it++) {
		if(buscado.compare(it->first) == 0)
			return true;
	}
	return false;
}
bool ParserConsultas::hayInputDimension(std::string &datosDeTabla, unsigned int consulta) {
	std::string buscado = getDato(datosDeTabla, consulta);

	std::map<std::string, std::vector<std::string> >::iterator it = mapInputsDimensiones.begin();
	for(; it != mapInputsDimensiones.end(); it++) {
		if(buscado.compare(it->first) == 0)
			return true;
	}
	return false;
}
bool ParserConsultas::hayInputHecho(std::string &datosDeTabla, unsigned int consulta) {
	std::string buscado = getDato(datosDeTabla, consulta);

	std::map<std::string, std::vector<std::string> >::iterator it = mapInputsHechos.begin();
	for(; it != mapInputsHechos.end(); it++) {
		if(buscado.compare(it->first) == 0)
			return true;
	}
	return false;
}

bool ParserConsultas::hayGrafico(std::string &datosDeTabla, unsigned int consulta) {
	std::string buscado = getDato(datosDeTabla, consulta);

	std::map<std::string, std::string>::iterator it = mapGraficos.begin();
	for(; it != mapGraficos.end(); it++) {
		if(buscado.compare(it->first) == 0)
			return true;
	}
	return false;
}

std::string ParserConsultas::getNombreTabla(std::string & datosDeTabla) {
	size_t pos = datosDeTabla.find_first_of(Util::SEPARADORFILECONSULTA, 0);
	pos = datosDeTabla.find_first_of(Util::SEPARADORFILECONSULTA, pos + 1);
	return datosDeTabla.substr(pos + 1);
}

unsigned int ParserConsultas::getNumeroTabla(std::string& datosDeTabla) {
	size_t pos1 = datosDeTabla.find_first_of(Util::SEPARADORFILECONSULTA, 0);
	size_t pos2 = datosDeTabla.find_first_of(Util::SEPARADORFILECONSULTA, pos1 + 1);
	return Util::stringToInt(datosDeTabla.substr(pos1 + 1, pos2 - pos1 -1));
}

void ParserConsultas::mostrar() {
	std::vector<std::string>::iterator it=datosDeTablas.begin();

	for(;it!=datosDeTablas.end();it++) {
		std::cout<<"DATOS DE TABLA Con NOMBRE: "<<*it<<std::endl;
		unsigned int cant= cantConsultasPorTabla[*it];
		std::cout<<"cant consultas: "<<cant<<std::endl;
		for(unsigned int i=1;i<=cant;i++) {
			if(hayFiltro(*it,i)) {
			std::cout<<"filtros:\n";
			std::vector<std::string>::iterator iF=getFiltros(*it,i).begin();
			for(;iF!=getFiltros(*it,i).end();iF++)
				std::cout<<*iF<<std::endl;
			}
			if(hayInputDimension(*it,i)) {
			std::cout<<"inputs dimensiones:\n";
			std::vector<std::string>::iterator iID=getInputsDimensiones(*it,i).begin();
			for(;iID!=getInputsDimensiones(*it,i).end();iID++)
				std::cout<<*iID<<std::endl;
			}
			if(hayInputHecho(*it,i)) {
			std::cout<<"inputs hechos:\n";
			std::vector<std::string>::iterator iIH=getInputsHechos(*it,i).begin();
			for(;iIH!=getInputsHechos(*it,i).end();iIH++)
				std::cout<<*iIH<<std::endl;
			}

			if(hayGrafico(*it,i))
				std::cout<<"grafico: "<<getGrafico(*it,i);
		}
	}
}
